#ifndef GAMEPANEL_H
#define GAMEPANEL_H

/* 游戏主窗口 */
#include "gamecontrol.h"
#include "card.h"
#include "cardpanel.h"
#include "animationwindow.h"
#include "countdown.h"
#include "bgmcontrol.h"
#include <QLabel>
#include <QMainWindow>
#include <QMap>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui {
class GamePanel;
}
QT_END_NAMESPACE

class GamePanel : public QMainWindow
{
    Q_OBJECT

public:
    using orderMap = QMap<int, QPair<QByteArray, int>>;

    GamePanel(QWidget *parent = nullptr);
    ~GamePanel();

    // 动画特效的枚举类型
    enum AnimationType { ShunZi, LianDui,  JokerBomb, Bomb, Plane, Bet };

    // 初始化游戏控制类信息
    void gameControlInit();
    // 更新分数面板上面的分数
    void updatePlayerScore();
    // 切割并存储图片
    void initCardMap();
    // 裁剪图片
    void cropImage(QPixmap& pix, int x, int y, const Card& c);
    // 初始化按钮组
    void initButtonsGroup();
    // 初始化玩家在窗口中的上下文环境
    void initPlayerContext();
    // 初始化游戏场景
    void initGameScene();
    // 处理游戏的状态
    void gameStatusProcess(GameControl::GameStatus status);
    // 处理发牌状态
    void startDispatchCard();
    // 移动扑克牌
    void cardMoveStep(Player* player, int curPos);            
    // 处理分发得到的牌
    void disposeCard(Player* player, const Cards& cards);
    // 更新扑克牌在窗口中的显示
    void updatePlayerCards(Player* player);
    // 加载玩家的头像
    QPixmap loadRoleImage(Player::Sex sex, Player::Direction direct, Player::Role role);
    // 开始游戏
    void startGame();
    void startGame(int index);



    // 显示特效动画窗口
    void showAnimationWindow(AnimationType type, int bet = 0);
    // 隐藏玩家打出的牌
    void hidePlayerDropCards(Player* player);
    // 显示玩家的最终得分
    void showEndingScorePanel();
    // 初始化闹钟倒计时窗口
    void initCountDown();



    // 处理网络模式下玩家的发牌次序与分数
    void initGamePanel(QByteArray msg);
    // 更新用户名和分数
    void updatePlayerInfo(orderMap& info);
    // 通知服务器当前玩家已经出牌了
    void notifyOtherPlayHand(Cards& cs);


    // 定时器处理发牌的动作
    void onDispatchCard();
    // 处理玩家状态的变化，更新窗口状态显示
    void onPlayerStatusChanged(Player* player, GameControl::PlayerStatus status);
    // 处理玩家抢地主的信号，并显示玩家是否叫地主的特效
    void onGrabLordBet(Player* player, int bet, bool flag);
    // 处理玩家的出牌
    void onDisposePlayHand(Player* player, const Cards& cards);
    // 处理玩家选牌
    void onCardSelected(Qt::MouseButton button);
    // 处理玩家出牌
    void onUserPlayHand();
    // 处理玩家放弃出牌
    void onUserPass();

protected:
    // 图像绘制事件
    void paintEvent(QPaintEvent* ev);
    // 鼠标移动事件
    void mouseMoveEvent(QMouseEvent* ev);
    // 窗口关闭事件
    void closeEvent(QCloseEvent* ev);

signals:
    // 信号处理函数: GameModel::GameModel
    void panelClose();  // 关闭主窗口

private:
    // 扑克牌的对齐方式
    enum CardAlign { Horizontal, Vertical };
    // 玩家的上下文相关信息
    struct PlayerContext
    {
        // 1. 玩家扑克牌显示的区域
        QRect cardRect;
        // 2. 出牌的区域
        QRect playHandRect;
        // 3. 扑克牌的对齐方式(水平 或者 垂直)
        CardAlign align;
        // 4. 扑克牌显示正面还是背面
        bool isFrontSide;
        // 5. 游戏过程中的提示信息，例如：不出
        QLabel* info;
        // 6. 玩家的头像
        QLabel* roleImage;
        // 7. 玩家刚打出的牌
        Cards lastCards;
    };

    Ui::GamePanel *ui;
    QPixmap m_bkImage;                              // 背景图片
    GameControl* m_gameCtrl;                        // 指向游戏控制类对象
    QVector<Player*> m_playerList;                  // 存储三个玩家的实例对象
    QMap<Card, CardPanel*> m_cardMap;               // 存储扑克牌
    QSize m_cardSize;                               // 扑克牌的尺寸
    QPixmap m_cardBackImage;                        // 扑克牌的背面图片
    QMap<Player*, PlayerContext> m_contextMap;      // 玩家的相关信息
    CardPanel* m_baseCard;                          // 发牌区域的扑克牌(底牌)
    CardPanel* m_moveCard;                          // 发走的扑克牌
    QVector<CardPanel*> m_last3Card;                // 最后预留的三章牌
    QPoint m_baseCardPos;                           // 扑克牌的中心位置
    GameControl::GameStatus m_gameStatus;           // 游戏状态
    QTimer* m_timer;                                // 定时器
    AnimationWindow* m_animation;                   // 叫地主时显示的下注分数窗口
    CardPanel* m_curSelCard;                        // 当前被选中的卡牌窗口对象
    QSet<CardPanel*> m_selectCards;                 // 保存被选中的扑克牌窗口对象
    QRect m_cardsRect;                              // 保存玩家剩余扑克牌的位置（所选牌的区域）
    QHash<CardPanel*, QRect> m_userCards;           // 保存玩家手牌与位置的关系
    CountDown* m_countDown;                         // 倒计时闹钟
    BGMControl* m_bgm;                              // 控制BGM的播放
    QByteArrayList  m_nameList;                     // 房间里玩家的用户名
};
#endif // GAMEPANEL_H
